#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <termios.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>

#include "color.h"
#include "guess.h"
#include "carton.h"
#include "homepage.h"
#include "leaderboard.h"
#include "configuration.h"

static void show_guess_help(void);

/**
 * @brief   显示猜数字游戏分支菜单
 * @param   void
 * @return  void
 */ 
void show_guess_menu(void)
{
    printf(L_RED);
    printf(BLINK);
    printf("\t==== Welcome to GUESS GAME!! ====\n\n\t");
    printf(NONE);

    printf(YELLOW);
    printf(""
        "========= GUESS NUMBER =========\n\t"
        "================================\n\t"
        "*                              *\n\t"
        "*       1. Game Start          *\n\t"
        "*                              *\n\t"
        "*       2.    Help             *\n\t"
        "*                              *\n\t"
        "*       3. Last Menu           *\n\t"
        "*                              *\n\t"
        "================================\n\t"
        "*                              *\n\t"
        "*       PLEASE SELECT 1~3:     *\n\t"
        "*                              *\n\t"
        "================================\n");
    printf(NONE);
}

/**
 * @brief   疯狂点击分支菜单输入判断, 按下1开始游戏,
 *          按下2查看帮助, 按下3返回主菜单.
 * @param   void
 * @return  void
 */
void choice_guess_menu(void)
{
    char input_guess_menu[32];

    while (1) {
        set_buffered_input(false);
        input_guess_menu[0] = getchar();
        set_buffered_input(true);

        switch (input_guess_menu[0]) {
            case START:
                game_guess_start();
                break;

            case HELP:
                system("clear");
                show_guess_help();
                break;

            case COME_BACK:
                system("clear");
                show_main_menu();
                choice_main_menu();
                break;

            default :
                system("clear");
                show_guess_menu();
                printf(L_RED "\n\tERROR INPUT!\r\n" NONE);
                choice_guess_menu();
                break;
        }
    }
}

/**
 * @brief   猜数字游戏查看帮助
 * @param   void
 * @return  void
 */
static void show_guess_help(void)
{
    show_guess_menu();

    printf(L_GREEN);
    printf("\n"
        "1. Game rules: You can only enter numbers between"
            " 1 and 100, and naughty will report an error!\r\n"
        "2. Game suggestion: Players can play the game with"
            " a half guess, gradually narrow the guess range"
            " until the final answer is guessed!\r\n");
    printf(NONE);

    choice_guess_menu();
}

/**
 * @brief   猜数字游戏时按下'q'退出的展示
 * @param   void
 * @return  void
 */
void show_guess_end(void)
{
    printf( YELLOW);
    printf( "                                    \n"
            "====================================\n"
            "======== OK,exit GUESS GAME ========\n"
            "====================================\n"
            "                                    \n");
    printf(NONE);
    guess_board_put();
}

/**
 * @brief   猜数字游戏时,获取输入数字并判断
 * @param   uint32_t minimun, uint32_t maximum
 * @return  uint8_t
 */
uint8_t get_number(uint32_t minimun, uint32_t maximum)
{
    char input[100];
    uint8_t length = 0, count = 0;
    uint32_t num = 0;
    uint8_t ret = 0;
    setstty();

    memset(input, 0, sizeof(input));

    if (maximum < minimun) {
        printf(" \tERROR: MAX < MIN  \r\n");
        return -ERROR;
    }

    scanf("%s", input);
    length = strlen(input)-1;
    
    if (input[1] == '\0' && input[0] > 'a') {

        switch (input[0]) {
            case 'r':
                ret = RETRY;
                break;

            case 'q':
                ret = QUIT;
                break;

            case 'b':   
                ret = BOARD;
                break;

            case 'm':
                ret = MENU;
                break;

            default:
                ret = -ERROR;
                break; 
        }
        return ret;
    }

    for (count = 0; count < length; count++) {

        if ( input[count] >= '0' && input[count] <= '9')
            continue;
        else {
            break;
        }
    }

    if (count == length) {

        num = atoi(input);
        if(num <= minimun || num >= maximum)
            return -ERROR;
        else
            return num;
    }
    else
        return -ERROR;

    renew();
}

/**
 * @brief   猜数字开始游戏初始化
 * @param   void
 * @return  void
 */
void game_guess_start(void)
{
    struct game guess;

    uint32_t guess_input = 0;
    char quit_input[8];
    guess.range_max = RANG_MAX;
    guess.range_min = RANG_MIN;
    guess.count = GUESS_COUNT;
    /*
     * 1. Get a random number
     */
    srand(time(NULL));
    guess.random_num = rand()%100+1;
    
    system("clear");
    carton_buddha();
    printf( L_RED BLINK
            "\n\n============ GAME START !!! ============\n"
            NONE);
    printf( YELLOW
            "'r' -Restart  'q' -Quit  'b' -LeaderBorad  'm' -Menu\r\n"
            NONE);

    while (1) {

        printf( YELLOW "The Number Between:%d ~ %d\r\n\n" NONE, guess.range_min, guess.range_max );
        guess_input = get_number(guess.range_min, guess.range_max);
        
        if (guess_input < guess.range_min) {

            printf(L_RED "ERROR INPUT ！！\r\n" NONE);
            continue;
        }

        /* 
         * When Game doing:
         * 1.input 'r',restart the guess. 
         * 2.input 'q',end the guess.
         * 3.input 'b',see the leaderboard, and then Enter 'r' return the game
         * 4.input 'm', return the menu.
         */
        if (guess_input >100) {

            switch (guess_input) {
                case RETRY:
                    game_guess_start();
                    break;

                case QUIT:
                    system("clear");
                    show_guess_end();
                    exit(EXIT_SUCCESS);
                    break;

                case BOARD:
                    system("clear");
                    guess_board_put();
                    printf(YELLOW "\n\nEnter 'r' return the game:\n" NONE);
                    while (1) {
                        set_buffered_input(false);
                        quit_input[0] = getchar();
                        set_buffered_input(true);

                        if (quit_input[0] != EOF && quit_input[0] == 'r') {
                            system("clear");
                            break;
                        } else
                            continue;
                    }
                    break;

                case MENU:
                    system("clear");
                    show_guess_menu();
                    choice_guess_menu();
                    break;

                default:
                    if (guess_input != '\n')
                        printf(L_RED "ERROR INPUT ！！\r\n" NONE);
                    break;
            }
        }
         /**
         * 1.Compare the number entered by the user with the correct answer, 
         *   and then display the corresponding hints.
         */
        if (guess_input > guess.random_num) 
            guess.count++;

        if (guess_input < guess.random_num)
            guess.count++;

        if (guess_input == guess.random_num) {

            guess.count++;
            guess_score_get(guess.count);

            if (guess.count <= 7) {

                carton_good();
                printf(YELLOW);
                printf("Yes, the answer is:%d, good!\n", guess.random_num);
                printf("You used %d times to guess the answer.\n", guess.count);
                printf(NONE);
            } else if (guess.count > 7) {

                carton_stupid();
                printf(YELLOW);
                printf("Yes, the answer is: %d ,so slow !\n", guess.random_num);
                printf("You used %d times to guess the answer.\n", guess.count);
                printf(NONE);
            } else {

                printf(L_RED "ERROR!\n" NONE);
            }
            putchar('\n');
            guess_board_put();
            
            /*
             * 1.游戏结束后,输入任意除了空格和回车的按键返回猜数字菜单;
             *   输入空格则退出游戏
             */
            while (1) {
                set_buffered_input(false);
                quit_input[0] = getchar();
                set_buffered_input(true);

                if (quit_input[0] != EOF && quit_input[0] == '\n') {
                    printf("\nAnything key expect ENTER to menu(SPACE to quit):\n");
                    continue;
                }
                if (quit_input[0] != EOF && quit_input[0] != ' ') {
                    system("clear");
                    show_guess_menu();
                    choice_guess_menu();
                } 
                if (quit_input[0] == ' ') 
                    exit(EXIT_SUCCESS);
            }
        } else if ( guess_input < guess.random_num 
                    && guess_input <= 100 
                    && guess_input >= 0) {
               guess.range_min = guess_input;
        } else if ( guess_input > guess.random_num 
                    && guess_input <= 100 
                    && guess_input >= 0) {
              guess.range_max = guess_input;
        } else
            continue;
    }
}